﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
using Newtonsoft.Json;

namespace VienApi
{
    public class VienApiHelper : INotifyPropertyChanged
    {
        private string userId = null;
        public static ChromiumWebBrowser browser;
        internal bool vienShow = true;
        private byte[] bFingerImage1 = new byte[0];
        private byte[] bFingerImage2 = new byte[0];
        private byte[] bFingerImage3 = new byte[0];
        public PictureBox pictureBox { get; set; }

        private string _messageText;

        public string CreateTemplateMessage
        {
            get { return _messageText; }
            set
            {
                if (_messageText != value)
                {
                    Console.WriteLine(value + "修改了变量");
                    _messageText = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(value));
                }
            }
        }

        private bool isOpened = false;

        public event PropertyChangedEventHandler PropertyChanged;

        public bool IsOpened { get { return isOpened; } set { isOpened = value; } }

        public VienApiHelper(PictureBox pictureBox)
        {
            this.pictureBox = pictureBox;
        }
        public int fvdev_get(int iFdvs)
        {
            iFdvs = 0;
            VienApiImport.fvdev_get_count(ref iFdvs);
            return iFdvs;
        }

        //打开设备
        public ApiResult Open(ChromiumWebBrowser browser1)
        {
            browser = browser1;
            ApiResult ret = new ApiResult();
            var iFdevs = 0;

            VienApiImport.fvdev_get_count(ref iFdevs);
            if (iFdevs == 0)
            {
                ret.Code = -1;
                ret.Message = "没有发现设备！";
                this.CreateTemplateMessage = ret.Message;
                return ret;
            }
            if (pictureBox != null)
            {
                isOpened = VienApiImport.fvdev_open(0, pictureBox.Handle);
            }

            if (!isOpened)
            {
                ret.Code = -1;
                ret.Message = "打开设备失败！";
                this.CreateTemplateMessage = ret.Message;
                return ret;
            }
            //title_text = "设备打开成功";
            string spath = Application.StartupPath + "\\model";

            if (!System.IO.Directory.Exists(spath))
            {
                try
                {
                    System.IO.Directory.CreateDirectory(spath);
                }
                catch (Exception)
                {
                }
            }

            int inum = 0; // unused
            if (!VienApiImport.fv_load_model(spath, ref inum))
            {
                ret.Code = -5;
                ret.Message = "加截模板库失败！" + spath;
                this.CreateTemplateMessage = ret.Message;
                return ret;
            }
            return ret;
        }
        //关闭设备
        public void Close()
        {
            if (VienApiImport.fvdev_close())
            {
                isOpened = false;
            }
        }

        //验证指纹
        public ApiResult ValidateVein()
        {
            ApiResult ret = new ApiResult();
            int ista = 0;
            if (VienApiImport.fvdev_get_state(ref ista))
            {
                if (ista == 3)
                {
                    byte[] bimg = new byte[80000];
                    int ilen = bimg.Length;
                    if (VienApiImport.fvdev_grab(ref bimg[0], ref ilen))
                    {
                        byte[] btmp = new byte[ilen];
                        Array.Copy(bimg, btmp, ilen);
                        bimg = btmp;

                        int ia = 0;
                        int iq = -1;
                        if (VienApiImport.fv_quality(bimg, ilen, ref ia, ref iq))
                        {
                            if (iq == 0)
                            {
                                int iin = 0;
                                float ft = 0.0f;
                                float fs = 0.0f;
                                if (VienApiImport.fv_user_index(ref bimg[0], ilen, ref iin, ft, ref fs, false))
                                {
                                    if (iin > 0)
                                    {
                                        ret.Message = "登录成功！";
                                        ret.Data = iin.ToString();
                                        return ret;
                                    }
                                }
                                else
                                {
                                    ret.Code = -3;
                                    ret.Message = "用户不存在！";
                                    return ret;
                                }
                            }
                        }
                    }
                    ret.Code = -4;
                    ret.Message = "图片质量不合格！";
                }
                else
                {
                    ret.Code = -1;
                    ret.Message = "请正确按压手指！";
                }
            }
            Console.WriteLine(ret);
            return ret;
        }

        //删除指静脉
        internal uint delFvuser(uint ifv)
        {
            if (ifv > 0)
            {
                if (VienApiImport.fv_user_del(ifv))
                {
                    this.CreateTemplateMessage = "删除成功！";
                    return 0;
                }
                else
                {
                    this.CreateTemplateMessage = "未删除到指定序列！";
                    return 1;
                }
            }
            else
            {
                this.CreateTemplateMessage = "请输入正确的序号！";
                return 1;
            }
        }
        //创建指纹模板
        public void CreateTemplate(string id)
        {
            userId = id;
            var t = new System.Threading.Thread(createTemplateThread);
            t.Start(0);
            vienShow = true;

        }

        private void createTemplateThread(object parameter)
        {
            int iFinger = (int)parameter; // 将参数转换为你需要的类型
            int ista = 0;
            int iFingerCount = 0;
            bool success = true;
            int timeout = 20000;
            DateTime t1 = DateTime.Now;
            DateTime t2 = DateTime.Now;
            var ts = (t2 - t1).TotalMilliseconds;
            while (success && iFingerCount <3 && ts <= timeout && vienShow)
            {
                t2 = DateTime.Now;
                ts = (t2 - t1).TotalMilliseconds;
                //System.Threading.Thread.Sleep(500);
                bool flg = VienApiImport.fvdev_get_state(ref ista);
                System.Threading.Thread.Sleep(50);
                //if (ista == 0)
                //{         
                //    title_text = "未检测到手指或手指按压的位置不全！";
                ////continue;
                //    return;
                //}

                if (ista != 3)
                {
                    this.CreateTemplateMessage = "请按压第" + (iFingerCount + 1) + "次手指后抬手！";
                    continue;
                }
                byte[] bimg = new byte[80000];
                int ilen = bimg.Length;
                if (!VienApiImport.fvdev_grab(ref bimg[0], ref ilen))
                {
                    continue;
                }
                byte[] btmp = new byte[ilen];
                Array.Copy(bimg, btmp, ilen);
                bimg = btmp;

                int ia = 0; int iq = -1;
                if (!VienApiImport.fv_quality(bimg, ilen, ref ia, ref iq))
                {
                    this.CreateTemplateMessage = "质量不合格";
                    continue;
                }
                if (iq > 0)
                {
                    this.CreateTemplateMessage = "质量不合格";
                    continue;
                }

                VienApiImport.fvdev_get_state(ref ista);
                if (ista != 0)
                {
                    while (true)
                    {
                        VienApiImport.fvdev_get_state(ref ista);
                        if (ista == 0)
                        {
                            break;
                        }
                        else
                        {
                            this.CreateTemplateMessage = "请抬手指";
                        }
                        System.Threading.Thread.Sleep(100);

                    }
                }

                int iin = 0;
                float ft = 0.0f;
                float fs = 0.0f;
                if (VienApiImport.fv_user_index(ref bimg[0], ilen, ref iin, ft, ref fs, false))
                {
                    if (iin > 0)
                    {
                        this.CreateTemplateMessage = "该手指图模已注册！请切换其它手指注册";
                        System.Threading.Thread.Sleep(500);
                        continue;
                    }
                    else
                    {
                        fvuserIndesOF(bimg, ilen, ref iFingerCount); // 手指可用
                    }
                }
                else
                {
                    fvuserIndesOF(bimg, ilen, ref iFingerCount); // 手指可用
                }
            }
        }

        private void fvuserIndesOF(byte[] bimg, int ilen, ref int iFingerCount)
        {
            byte[] bImage = new byte[1];
            byte[] bOutModel = new byte[ilen];
            int bOutModelLen = bOutModel.Length;
            float score = 0;
            if (VienApiImport.fv_extract_model(ref bimg[0], ilen, ref bImage[0], 0, ref bImage[0], 0, ref bOutModel[0], ref bOutModelLen))
            {
                if (iFingerCount == 0)
                {
                    bFingerImage1 = bimg;
                    iFingerCount = 1;
                    //title_text = "第1次采图成功！请继续采图...";
                    this.CreateTemplateMessage = "请按第2次手指";
                    return;
                }
                else if (iFingerCount == 1)
                {
                    bool flg = VienApiImport.fv_match(ref bimg[0], ilen, ref bFingerImage1[0], ref score);
                    Console.WriteLine(score);
                    if (score < 0.4)
                    {
                        this.CreateTemplateMessage = "不是同一根手指";
                        return;
                    }
                    bFingerImage2 = bimg;
                    iFingerCount = 2;
                    //title_text = "第2次采图成功！请继续采图...";
                    this.CreateTemplateMessage = "请按第3次手指";
                    return;
                }
                else if (iFingerCount == 2)
                {
                    bool flg = VienApiImport.fv_match(ref bimg[0], ilen, ref bFingerImage2[0], ref score);
                    Console.WriteLine(score);
                    if (score < 0.4)
                    {
                        this.CreateTemplateMessage = "不是同一根手指";
                        return;
                    }
                    bFingerImage3 = bimg;
                    iFingerCount = 3;
                    this.CreateTemplateMessage = "3次采图完成！";
                    saveTemplate();
                  
                }
            }
            else
            {
                this.CreateTemplateMessage = "图片质量不合格！请继续第" + iFingerCount.ToString() + "次采图！";
            }
        }
        public class Person
        {
            public uint id { get; set; }
            public string code { get; set; }
            public string data { get; set; }
        }
        private void saveTemplate()
        {
            if (bFingerImage1 == null || bFingerImage2 == null || bFingerImage3 == null
                || bFingerImage1.Length <= 0 || bFingerImage2.Length <= 0 || bFingerImage3.Length <= 0)
            {
                this.CreateTemplateMessage = "请先完成【3次采图】！";
                return;
            }
          
        uint iFingerIndex = 0; // 输出用户存入的index
            string fileName = "data.txt"; // 文件名
            List<Person> peopleList = new List<Person>();

            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); // 文件完整路径
            if (VienApiImport.fv_user_add(bFingerImage1, bFingerImage1.Length, bFingerImage2, bFingerImage2.Length, bFingerImage3, bFingerImage3.Length, ref iFingerIndex))
            {
                this.CreateTemplateMessage = "【建模】成功";
                string spath = Application.StartupPath + "\\model";
                string inputFilePath = spath + "\\" + iFingerIndex + "\\1.dat"; // 输入文件路径
                byte[] fileBytes = File.ReadAllBytes(inputFilePath);
                string ifv = userId;
                // 将文件内容转换为 Base64 编码
                string base64String = Convert.ToBase64String(fileBytes);
                try
                {
                    // 判断文件是否存在
                    if (!File.Exists(filePath))
                    {
                        // 如果文件不存在，创建新文件并写入对象数组
                        peopleList.Add(new Person { id = 0, code = ifv, data = base64String });

                        string jsonContent = JsonConvert.SerializeObject(peopleList, Formatting.Indented);
                        File.WriteAllText(filePath, jsonContent);
                        Console.WriteLine("文件已创建并写入对象数组。");
                    }
                    else
                    {
                        // 如果文件已经存在，读取文件中的 JSON 数据并将其反序列化为对象数组
                        string jsonContent = File.ReadAllText(filePath);
                        peopleList = JsonConvert.DeserializeObject<List<Person>>(jsonContent);

                        // 向数组中添加新的对象
                        peopleList.Add(new Person { id = iFingerIndex, code = ifv, data = base64String });

                        // 将更新后的数组重新写入文件
                        jsonContent = JsonConvert.SerializeObject(peopleList, Formatting.Indented);
                        File.WriteAllText(filePath, jsonContent);
                        Console.WriteLine("已向对象数组中添加新的对象并更新到文件。");
                    }

                    string javascriptCode = $"this.showData('{iFingerIndex}','{ifv}','{base64String}')";
                    browser.GetMainFrame().ExecuteJavaScriptAsync(javascriptCode);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"处理文件时出现错误：{ex.Message}");
                }
               
                return;
            }
            else
            {
                this.CreateTemplateMessage = "图片质量不合格，请重新操作【3次采图】！";
            }
        }

    }

    public class ApiResult
    {
        public int Code { get; set; }
        public string Message { get; set; }
        public object Data { get; set; }
    }

    public class VienApiImport
    {
        //设备数
        [DllImport("FingerVeinDLL.dll", EntryPoint = "fvdev_get_count", CharSet = CharSet.Ansi)]
        public static extern bool fvdev_get_count(ref int count);

        //设备打开
        [DllImport("FingerVeinDLL.dll", EntryPoint = "fvdev_open", CharSet = CharSet.Ansi)]
        public static extern bool fvdev_open(int devno, IntPtr hwnd);

        //设备关闭
        [DllImport("FingerVeinDLL.dll", EntryPoint = "fvdev_close", CharSet = CharSet.Ansi)]
        public static extern bool fvdev_close();

        //1:1比对
        [DllImport("FingerVeinDLL.dll", EntryPoint = "fv_match", CharSet = CharSet.Ansi)]
        public static extern bool fv_match(ref byte img, int imgLen, ref byte model, ref float score);

        //1:N比对
        [DllImport("FingerVeinDLL.dll", EntryPoint = "fv_user_index", CharSet = CharSet.Ansi)]
        public static extern bool fv_user_index(ref byte img, int len, ref int indexID, float threshold, ref float score, bool bUpdate);

        //设备探测状态
        [DllImport("FingerVeinDLL.dll", EntryPoint = "fvdev_get_state", CharSet = CharSet.Ansi)]
        public static extern bool fvdev_get_state(ref int state);//0没有，3手指正常按压

        //取得原图
        [DllImport("FingerVeinDLL.dll", EntryPoint = "fvdev_grab", CharSet = CharSet.Ansi)]
        public static extern bool fvdev_grab(ref byte img, ref int len);//初值不小于78000个字节

        //取得jpg图
        [DllImport("FingerVeinDLL.dll", EntryPoint = "fvdev_getJpg", CharSet = CharSet.Ansi)]
        public static extern bool fvdev_getJpg(ref byte img, ref int len, ref byte imgDec);

        //检测手指图质量
        [DllImport("FingerVeinDLL.dll", EntryPoint = "fv_quality", CharSet = CharSet.Ansi)]
        public static extern bool fv_quality(byte[] img, int len, ref int a, ref int q);//0质量通过，2001不好，2003不行

        //获取模板
        [DllImport("FingerVeinDLL.dll", EntryPoint = "fv_extract_model", CharSet = CharSet.Ansi)]
        public static extern bool fv_extract_model(ref byte picData1, int picLen1, ref byte picData2, int picLen2, ref byte picData3, int picLen3, ref byte model, ref int modelLen);

        //添加用户
        [DllImport("FingerVeinDLL.dll", EntryPoint = "fv_user_add", CharSet = CharSet.Ansi)]
        public static extern bool fv_user_add(byte[] picData1, int picLen1, byte[] picData2, int picLen2, byte[] picData3, int picLen3, ref uint indexID);

        //删除用户
        [DllImport("FingerVeinDLL.dll", EntryPoint = "fv_user_del", CharSet = CharSet.Ansi)]
        public static extern bool fv_user_del(uint indexID);

        //调入之前/设定dat文件为模板存储目录
        [DllImport("FingerVeinDLL.dll", EntryPoint = "fv_load_model", CharSet = CharSet.Ansi)]
        public static extern bool fv_load_model(string modelPath, ref int num);

    }
}
